/* ************************************************************************
> File Name:     hashtable.c
> Author:        zhfu
> mail:          3346897597@qq.com
> Created Time:  2022年05月04日 星期三 22时02分02秒
> Description:   
 ************************************************************************/
#include<stdlib.h>
#include"stringhash.h"
#include"stringlist.h"

static int find_index(my_hash *h, int index)
{
    int *p = h->hash_value;
    int i = 0;
    for (; i < h->len; ++i){
        if (index == p[i]){
            return i;
        }
    }

    return -1;
}

static void rehash(my_hash *h){
    int *p = malloc(h->len * sizeof  (int));
    link *t = malloc(h->len * sizeof (h->p) );
    int i, j = 0;
    for (i = 0; i <= h->i; ++i){
        if ((h->hash_value)[i] != -1){
            p[j] = (h->hash_value)[i];
            t[j] = (h->p)[i];
            ++j;
        }
    }
    free(h->hash_value);
    free(h->p);
    h->hash_value = p;
    h->p = t;
}

link search(my_hash *h, char *v)
{
   if (!h->p){
       return NULL;
   }

   int k = (h->my_hashfunc)(v);
   if (find_index(h, k) == -1){
       return NULL;
   }

   stringlist l = {(h->p)[find_index(h, (h->my_hashfunc)(v))]};
   return list_search(&l, v);
}


void insert(my_hash *h, char *v)
{
    if (!h->p){
        h->p = malloc(h->len * sizeof (h->p) );
        h->hash_value = malloc(h->len * sizeof  (int));
        int i;
        for (i = 0; i < h->len; ++i){
            (h->p)[i] = NULL;
            (h->hash_value)[i] = -1;
        }
    }

    int index = (h->my_hashfunc)(v);
    int k = find_index(h, index);
    if (k == -1){
        stringlist l = {NULL};
        list_insert(&l, v);
        (h->p)[h->i] = l.head;
        (h->hash_value)[h->i] = index;
        ++(h->i);
        return;
    }

    stringlist l = {(h->p)[k]};
    list_insert(&l, v);
    (h->p)[k] = l.head;

    return;
}

void delete(my_hash *h, char *v)
{
    if (search(h, v)){
        int index = (h->my_hashfunc)(v);
        stringlist l = {(h->p)[find_index(h, index)]};
        list_delete(&l, v);
        (h->p)[find_index(h, index)] = l.head;
        if (!l.head){
            (h->hash_value)[find_index(h, index)] = -1;
            rehash(h);
            --(h->i);
        }
    }
}

void print_hash(my_hash h)
{
    int i;
    for (i = 0; i < h.len; ++i){
        stringlist l = {(h.p)[i]};
        print_list(&l);
    }
}

void free_hash(my_hash *h)
{
    if (h){
        int i;
        for (i = 0; i < h->len; ++i){
            stringlist l = {(h->p)[i]};
            free_list(&l);
        }
    }
}
